package com.croot.infra.${projectFlag}.service.basic;

import com.croot.infra.common.exception.RepositoryException;
import com.croot.infra.common.idgen.IdGenService;
import com.croot.infra.common.rdb.consts.DelFlagEnum;
import com.croot.infra.${projectFlag}.adapter.thread.LoginThreadLocal;
import com.croot.infra.${projectFlag}.adapter.rdb.${entityName}Repository;
import com.croot.infra.${projectFlag}.adapter.rdb.po.${entityName}PO;
import com.croot.infra.${projectFlag}.api.basic.${entityName}BasicAPI;
import com.croot.infra.${projectFlag}.dto.request.${entityName}IdReqDTO;
import com.croot.infra.${projectFlag}.dto.request.${entityName}ReqDTO;
import com.croot.infra.${projectFlag}.dto.response.${entityName}RespDTO;
import com.croot.infra.${projectFlag}.dto.response.${entityName}IdRespDTO;
import com.croot.infra.${projectFlag}.exception.${entityName}ServiceException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
public class ${entityName}BasicService implements ${entityName}BasicAPI {

    @Autowired
    private ${entityName}Repository ${entityParamName}Repository;

    @Autowired
    private IdGenService idGenService;

    @Override
    public List<${entityName}RespDTO> list(${entityName}ReqDTO ${entityParamName}ReqDTO) throws ${entityName}ServiceException {
        try {
            List<${entityName}PO> ${entityParamName}POList = qry${entityName}List(${entityParamName}ReqDTO);

            if (judge${entityName}POListIsEmpty(${entityParamName}POList)) {
                return buildResultOf${entityName}CountIsZero();
            }

            return get${entityName}RespDTOList(${entityParamName}POList);
        } catch (RepositoryException e) {
            throw new ${entityName}ServiceException(e.getErrCode(), e.getErrMsg());
        }
    }

    @Override
    public ${entityName}IdRespDTO add(${entityName}ReqDTO ${entityParamName}ReqDTO) throws ${entityName}ServiceException {
        try {
            ${entityName}PO ${entityParamName}PO = buildAdd${entityName}PO(${entityParamName}ReqDTO);
            ${entityParamName}Repository.insert(${entityParamName}PO);
            return ${entityName}IdRespDTO.buildFromPO(${entityParamName}PO);
        } catch (RepositoryException e) {
            throw new ${entityName}ServiceException(e.getErrCode(), e.getErrMsg());
        }
    }

    @Override
    public void delete(${entityName}IdReqDTO ${entityParamName}IdReqDTO) throws ${entityName}ServiceException {
        ${entityName}PO ${entityParamName}PO = ${entityParamName}IdReqDTO.convertToPO();

        Date date = new Date();
        ${entityParamName}PO.setUpdateTime(date);
        ${entityParamName}PO.setUpdater(LoginThreadLocal.get());
        try {
            ${entityParamName}Repository.delete(${entityParamName}PO);
        } catch (RepositoryException e) {
            throw new ${entityName}ServiceException(e.getErrCode(), e.getErrMsg());
        }
    }

    @Override
    public void update(${entityName}ReqDTO ${entityParamName}ReqDTO) throws ${entityName}ServiceException {
        ${entityName}PO ${entityParamName}PO = buildUpdate${entityName}PO(${entityParamName}ReqDTO);
        try {
            ${entityParamName}Repository.update(${entityParamName}PO);
        } catch (RepositoryException e) {
            throw new ${entityName}ServiceException(e.getErrCode(), e.getErrMsg());
        }
    }

    @Override
    public List<${entityName}RespDTO> listPage(${entityName}ReqDTO ${entityParamName}ReqDTO) throws ${entityName}ServiceException {
        ${entityName}PO ${entityParamName}PO = build${entityName}ByPage(${entityParamName}ReqDTO);
        List<${entityName}PO> ${entityParamName}POList = ${entityParamName}Repository.list(${entityParamName}PO);

        if (judge${entityName}POListIsEmpty(${entityParamName}POList)) {
            return buildResultOf${entityName}CountIsZero();
        }

        return get${entityName}RespDTOList(${entityParamName}POList);
    }

    @Override
    public Long count(${entityName}ReqDTO ${entityParamName}ReqDTO) throws ${entityName}ServiceException {
        ${entityName}PO ${entityParamName}PO = build${entityName}ByPage(${entityParamName}ReqDTO);
        return ${entityParamName}Repository.count(${entityParamName}PO);
    }

    @Override
    public ${entityName}RespDTO getById(${entityName}IdReqDTO ${entityParamName}IdReqDTO) throws ${entityName}ServiceException {
        ${entityName}PO ${entityParamName}PO = ${entityParamName}Repository.getById(Long.parseLong(${entityParamName}IdReqDTO.getId()));

        if (Objects.isNull(${entityParamName}PO)) {
            return null;
        }

        return ${entityName}RespDTO.buildFromPO(${entityParamName}PO);
    }

    private List<${entityName}PO> qry${entityName}List(${entityName}ReqDTO ${entityParamName}ReqDTO) {

        ${entityName}PO ${entityParamName}ReqPO = ${entityParamName}ReqDTO.convertToPO();
        ${entityParamName}ReqPO.setDelFlag(DelFlagEnum.NORMAL.getCode());

        return ${entityParamName}Repository.list(${entityParamName}ReqPO);
    }

    private ${entityName}PO buildAdd${entityName}PO(${entityName}ReqDTO ${entityParamName}ReqDTO) {
        ${entityName}PO ${entityParamName}PO = ${entityParamName}ReqDTO.convertToPO();
        ${entityParamName}PO.setId(idGenService.getNextId());

        Date date = new Date();
        ${entityParamName}PO.setCreateTime(date);
        ${entityParamName}PO.setCreator(LoginThreadLocal.get());
        ${entityParamName}PO.setUpdateTime(date);
        ${entityParamName}PO.setUpdater(LoginThreadLocal.get());
        ${entityParamName}PO.setDelFlag(DelFlagEnum.NORMAL.getCode());

        return ${entityParamName}PO;
    }

    private ${entityName}PO buildUpdate${entityName}PO(${entityName}ReqDTO ${entityParamName}ReqDTO) {
        ${entityName}PO ${entityParamName}PO = ${entityParamName}ReqDTO.convertToPO();

        Date date = new Date();
        ${entityParamName}PO.setUpdateTime(date);
        ${entityParamName}PO.setUpdater(LoginThreadLocal.get());

        return ${entityParamName}PO;
    }

    private boolean judge${entityName}POListIsEmpty(List<${entityName}PO> ${entityParamName}POList) {
        return CollectionUtils.isEmpty(${entityParamName}POList);
    }

    private List<${entityName}RespDTO> buildResultOf${entityName}CountIsZero() {
        return new ArrayList<>();
    }

    private List<${entityName}RespDTO> get${entityName}RespDTOList(List<${entityName}PO> ${entityParamName}POList) {

        List<${entityName}RespDTO> ${entityParamName}List = new ArrayList<>();
        ${entityName}RespDTO ${entityParamName}RespDTO = null;

        for (${entityName}PO ${entityParamName}PO : ${entityParamName}POList) {
            if (!Objects.isNull(${entityParamName}PO)) {
                ${entityParamName}RespDTO = ${entityName}RespDTO.buildFromPO(${entityParamName}PO);
                ${entityParamName}List.add(${entityParamName}RespDTO);
            }
        }
        return ${entityParamName}List;
    }

    private ${entityName}PO build${entityName}ByPage(${entityName}ReqDTO ${entityParamName}ReqDTO){
        ${entityName}PO ${entityParamName}PO = ${entityParamName}ReqDTO.convertToPO();

        Integer pageNo = ${entityParamName}ReqDTO.getPageNo();
        Integer pageSize = ${entityParamName}ReqDTO.getPageSize();
        Integer offset = (pageNo - 1) * pageSize;
        ${entityParamName}PO.setOffset(offset);
        ${entityParamName}PO.setPageSize(pageSize);
        ${entityParamName}PO.setDelFlag(DelFlagEnum.NORMAL.getCode());
        return ${entityParamName}PO;
    }
}